package com.rzx.mybackend.aop;


import com.rzx.mybackend.annotation.CommentIdempotent;
import com.rzx.mybackend.entity.GameComment;
import com.rzx.mybackend.utils.RedissonUtil;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import java.util.concurrent.TimeUnit;

/**
 * CommentIdempotentAspect
 * 评论发布幂等性处理
 * @author renzhexian
 * @date 2025/7/24
 */
@Aspect
@Component
@RequiredArgsConstructor
public class CommentIdempotentAspect {

    private static final Logger log = LoggerFactory.getLogger(CommentIdempotentAspect.class);

    private final RedissonUtil redissonUtil;

    @Around("@annotation(idempotent)")
    public Object handleIdepotent(ProceedingJoinPoint joinPoint, CommentIdempotent idempotent) {

        log.info("CommentIdempotentAspect.handleIdepotent() - 进入幂等性处理");

        // 从切点获取GameComment对象
        GameComment comment = new GameComment();
        for (Object arg : joinPoint.getArgs()) {
            if (arg instanceof GameComment) {
                comment = (GameComment) arg;
                log.info("CommentIdempotentAspect.handleIdepotent() - 获取GameComment对象成功");
                break;
            }
        }

        // 构造Redis键
        String key= DigestUtils.md5DigestAsHex(("commented:" + comment.getUserId() + ":" + comment.getGameId() + ":" + comment.getCommentContent()).getBytes());

        // 检查Redis是否存在该key
        if (!redissonUtil.tryLock(key, 0, 30, TimeUnit.SECONDS)) {
            throw new RuntimeException("请勿重复提交");
        }

        try {
           joinPoint.proceed();
        } catch (Throwable e) {
            log.error("CommentIdempotentAspect.handleIdepotent() - 方法执行异常", e);
        }

        // 方法执行完毕后，存储该key到Redis
        redissonUtil.setString(key, "1", 5, TimeUnit.MINUTES);

        return comment;
    }

}
